// SPDX-License-Identifier: MIT
// Copyright (C) 2018-present iced project and contributors

package com.github.icedland.iced.x86.enc;

import org.junit.jupiter.api.*;
import com.github.icedland.iced.x86.dec.DecoderOptions;

final class BlockEncoder64_jkcc_Tests extends BlockEncoderTests {
	static final int bitness = 64;
	static final long origRip = 0x8000L;
	static final long newRip = 0x8000000000000000L;
	static final int DECODER_OPTIONS = BlockEncoderTests.DECODER_OPTIONS | DecoderOptions.KNC;

	@Test
	void jkcc_short_fwd() {
		byte[] originalData = new byte[] {
			/*0000*/ (byte)0xC4, (byte)0xE0, 0x50, 0x74, 0x09,// jkzd k5, short 0Eh
			/*0005*/ (byte)0xB0, 0x00,// mov al,0
			/*0007*/ (byte)0xC4, (byte)0xE0, 0x50, 0x75, 0x02,// jknzd k5, short 0Eh
			/*000C*/ (byte)0xB0, 0x01,// mov al,1
			/*000E*/ (byte)0xB0, 0x10,// mov al,10h
		};
		byte[] newData = new byte[] {
			/*0000*/ (byte)0xC4, (byte)0xE0, 0x50, 0x74, 0x09,// jkzd k5, short 0Eh
			/*0005*/ (byte)0xB0, 0x00,// mov al,0
			/*0007*/ (byte)0xC4, (byte)0xE0, 0x50, 0x75, 0x02,// jknzd k5, short 0Eh
			/*000C*/ (byte)0xB0, 0x01,// mov al,1
			/*000E*/ (byte)0xB0, 0x10,// mov al,10h
		};
		int[] expectedInstructionOffsets = new int[] {
			0x0000,
			0x0005,
			0x0007,
			0x000C,
			0x000E,
		};
		RelocInfo[] expectedRelocInfos = new RelocInfo[0];
		final int options = BlockEncoderOptions.NONE;
		encodeBase(bitness, origRip, originalData, newRip, newData, options, DECODER_OPTIONS, expectedInstructionOffsets, expectedRelocInfos);
	}

	@Test
	void jkcc_short_bwd() {
		byte[] originalData = new byte[] {
			/*0000*/ (byte)0xB0, 0x10,// mov al,10h
			/*0002*/ (byte)0xC4, (byte)0xE0, 0x50, 0x74, (byte)0xF9,// jkzd k5, short 0
			/*0007*/ (byte)0xB0, 0x00,// mov al,0
			/*0009*/ (byte)0xC4, (byte)0xE0, 0x50, 0x75, (byte)0xF2,// jknzd k5, short 0
			/*000E*/ (byte)0xB0, 0x01,// mov al,1
		};
		byte[] newData = new byte[] {
			/*0000*/ (byte)0xB0, 0x10,// mov al,10h
			/*0002*/ (byte)0xC4, (byte)0xE0, 0x50, 0x74, (byte)0xF9,// jkzd k5, short 0
			/*0007*/ (byte)0xB0, 0x00,// mov al,0
			/*0009*/ (byte)0xC4, (byte)0xE0, 0x50, 0x75, (byte)0xF2,// jknzd k5, short 0
			/*000E*/ (byte)0xB0, 0x01,// mov al,1
		};
		int[] expectedInstructionOffsets = new int[] {
			0x0000,
			0x0002,
			0x0007,
			0x0009,
			0x000E,
		};
		RelocInfo[] expectedRelocInfos = new RelocInfo[0];
		final int options = BlockEncoderOptions.NONE;
		encodeBase(bitness, origRip, originalData, newRip, newData, options, DECODER_OPTIONS, expectedInstructionOffsets, expectedRelocInfos);
	}

	@Test
	void jkcc_short_other_short() {
		byte[] originalData = new byte[] {
			/*0000*/ (byte)0xC4, (byte)0xE0, 0x50, 0x74, 0x09,// jkzd k5, short 0Eh
			/*0005*/ (byte)0xB0, 0x00,// mov al,0
			/*0007*/ (byte)0xC4, (byte)0xE0, 0x50, 0x75, 0x02,// jknzd k5, short 0Eh
			/*000C*/ (byte)0xB0, 0x01,// mov al,1
		};
		byte[] newData = new byte[] {
			/*0000*/ (byte)0xC4, (byte)0xE0, 0x50, 0x74, 0x0A,// jkzd k5, short 0Eh
			/*0005*/ (byte)0xB0, 0x00,// mov al,0
			/*0007*/ (byte)0xC4, (byte)0xE0, 0x50, 0x75, 0x03,// jknzd k5, short 0Eh
			/*000C*/ (byte)0xB0, 0x01,// mov al,1
		};
		int[] expectedInstructionOffsets = new int[] {
			0x0000,
			0x0005,
			0x0007,
			0x000C,
		};
		RelocInfo[] expectedRelocInfos = new RelocInfo[0];
		final int options = BlockEncoderOptions.NONE;
		encodeBase(bitness, origRip, originalData, origRip - 1, newData, options, DECODER_OPTIONS, expectedInstructionOffsets, expectedRelocInfos);
	}

	@Test
	void jkcc_short_other_near() {
		byte[] originalData = new byte[] {
			/*0000*/ (byte)0xC4, (byte)0xE0, 0x50, 0x74, 0x09,// jkzd k5, short 0Eh
			/*0005*/ (byte)0xB0, 0x00,// mov al,0
			/*0007*/ (byte)0xC4, (byte)0xE0, 0x50, 0x75, 0x02,// jknzd k5, short 0Eh
			/*000C*/ (byte)0xB0, 0x01,// mov al,1
		};
		byte[] newData = new byte[] {
			/*0000*/ (byte)0xC5, (byte)0xD0, (byte)0x84, 0x07, (byte)0xF0, (byte)0xFF, (byte)0xFF,// jkzd k5, near ptr 0Eh
			/*0007*/ (byte)0xB0, 0x00,// mov al,0
			/*0009*/ (byte)0xC5, (byte)0xD0, (byte)0x85, (byte)0xFE, (byte)0xEF, (byte)0xFF, (byte)0xFF,// jknzd k5, near ptr 0Eh
			/*0010*/ (byte)0xB0, 0x01,// mov al,1
		};
		int[] expectedInstructionOffsets = new int[] {
			0x0000,
			0x0007,
			0x0009,
			0x0010,
		};
		RelocInfo[] expectedRelocInfos = new RelocInfo[0];
		final int options = BlockEncoderOptions.NONE;
		encodeBase(bitness, origRip, originalData, origRip + 0x1000, newData, options, DECODER_OPTIONS, expectedInstructionOffsets, expectedRelocInfos);
	}

	@Test
	void jkcc_short_other_long() {
		byte[] originalData = new byte[] {
			/*0000*/ (byte)0xC4, (byte)0xE0, 0x50, 0x74, 0x0B,// jkzd k5, short 10h
			/*0005*/ (byte)0xB0, 0x00,// mov al,0
			/*0007*/ (byte)0xC4, (byte)0xE0, 0x50, 0x75, 0x05,// jknzd k5, short 11h
			/*000C*/ (byte)0xB0, 0x01,// mov al,1
			/*000E*/ (byte)0x90,// nop
		};
		byte[] newData = new byte[] {
			/*0000*/ (byte)0xC4, (byte)0xE0, 0x50, 0x75, 0x06,// jknzd k5, short 8
			/*0005*/ (byte)0xFF, 0x25, 0x15, 0x00, 0x00, 0x00,// jmp qword ptr [8000000000000020h]
			/*000B*/ (byte)0xB0, 0x00,// mov al,0
			/*000D*/ (byte)0xC4, (byte)0xE0, 0x50, 0x74, 0x06,// jkzd k5, short 12
			/*0012*/ (byte)0xFF, 0x25, 0x10, 0x00, 0x00, 0x00,// jmp qword ptr [8000000000000028h]
			/*0018*/ (byte)0xB0, 0x01,// mov al,1
			/*001A*/ (byte)0x90,// nop
			/*001B*/ (byte)0xCC, (byte)0xCC, (byte)0xCC, (byte)0xCC, (byte)0xCC,
			/*0020*/ 0x10, (byte)0xDE, (byte)0xBC, (byte)0x9A, 0x78, 0x56, 0x34, 0x12,
			/*0028*/ 0x11, (byte)0xDE, (byte)0xBC, (byte)0x9A, 0x78, 0x56, 0x34, 0x12,
		};
		int[] expectedInstructionOffsets = new int[] {
			0xFFFF_FFFF,
			0x000B,
			0xFFFF_FFFF,
			0x0018,
			0x001A,
		};
		RelocInfo[] expectedRelocInfos = new RelocInfo[] {
			new RelocInfo(RelocKind.OFFSET64, 0x8000000000000020L),
			new RelocInfo(RelocKind.OFFSET64, 0x8000000000000028L),
		};
		final int options = BlockEncoderOptions.NONE;
		final long origRip = 0x123456789ABCDE00L;
		encodeBase(bitness, origRip, originalData, newRip, newData, options, DECODER_OPTIONS, expectedInstructionOffsets, expectedRelocInfos);
	}

	@Test
	void jkcc_near_fwd_short() {
		byte[] originalData = new byte[] {
			/*0000*/ (byte)0xC5, (byte)0xD0, (byte)0x84, 0x0B, 0x00, 0x00, 0x00,// jkzd k5, near ptr 12h
			/*0007*/ (byte)0xB0, 0x00,// mov al,0
			/*0009*/ (byte)0xC5, (byte)0xD0, (byte)0x85, 0x02, 0x00, 0x00, 0x00,// jknzd k5, near ptr 12h
			/*0010*/ (byte)0xB0, 0x01,// mov al,1
			/*0012*/ (byte)0xB0, 0x10,// mov al,10h
		};
		byte[] newData = new byte[] {
			/*0000*/ (byte)0xC4, (byte)0xE0, 0x50, 0x74, 0x09,// jkzd k5, short 0Eh
			/*0005*/ (byte)0xB0, 0x00,// mov al,0
			/*0007*/ (byte)0xC4, (byte)0xE0, 0x50, 0x75, 0x02,// jknzd k5, short 0Eh
			/*000C*/ (byte)0xB0, 0x01,// mov al,1
			/*000E*/ (byte)0xB0, 0x10,// mov al,10h
		};
		int[] expectedInstructionOffsets = new int[] {
			0x0000,
			0x0005,
			0x0007,
			0x000C,
			0x000E,
		};
		RelocInfo[] expectedRelocInfos = new RelocInfo[0];
		final int options = BlockEncoderOptions.NONE;
		encodeBase(bitness, origRip, originalData, newRip, newData, options, DECODER_OPTIONS, expectedInstructionOffsets, expectedRelocInfos);
	}

	@Test
	void jkcc_near_fwd_near() {
		byte[] originalData = new byte[] {
			/*0000*/ (byte)0xC5, (byte)0xD0, (byte)0x84, (byte)0x8D, 0x00, 0x00, 0x00,// jkzd k5, near ptr 94h
			/*0007*/ (byte)0xB0, 0x00,// mov al,0
			/*0009*/ (byte)0xC5, (byte)0xD0, (byte)0x85, (byte)0x84, 0x00, 0x00, 0x00,// jknzd k5, near ptr 94h
			/*0010*/ (byte)0xB0, 0x01,// mov al,1
			/*0012*/ 0x64, 0x67, (byte)0xC7, (byte)0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
			/*001F*/ 0x64, 0x67, (byte)0xC7, (byte)0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
			/*002C*/ 0x64, 0x67, (byte)0xC7, (byte)0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
			/*0039*/ 0x64, 0x67, (byte)0xC7, (byte)0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
			/*0046*/ 0x64, 0x67, (byte)0xC7, (byte)0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
			/*0053*/ 0x64, 0x67, (byte)0xC7, (byte)0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
			/*0060*/ 0x64, 0x67, (byte)0xC7, (byte)0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
			/*006D*/ 0x64, 0x67, (byte)0xC7, (byte)0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
			/*007A*/ 0x64, 0x67, (byte)0xC7, (byte)0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
			/*0087*/ 0x64, 0x67, (byte)0xC7, (byte)0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
			/*0094*/ (byte)0xB0, 0x10,// mov al,10h
		};
		byte[] newData = new byte[] {
			/*0000*/ (byte)0xC5, (byte)0xD0, (byte)0x84, (byte)0x8D, 0x00, 0x00, 0x00,// jkzd k5, near ptr 94h
			/*0007*/ (byte)0xB0, 0x00,// mov al,0
			/*0009*/ (byte)0xC5, (byte)0xD0, (byte)0x85, (byte)0x84, 0x00, 0x00, 0x00,// jknzd k5, near ptr 94h
			/*0010*/ (byte)0xB0, 0x01,// mov al,1
			/*0012*/ 0x64, 0x67, (byte)0xC7, (byte)0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
			/*001F*/ 0x64, 0x67, (byte)0xC7, (byte)0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
			/*002C*/ 0x64, 0x67, (byte)0xC7, (byte)0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
			/*0039*/ 0x64, 0x67, (byte)0xC7, (byte)0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
			/*0046*/ 0x64, 0x67, (byte)0xC7, (byte)0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
			/*0053*/ 0x64, 0x67, (byte)0xC7, (byte)0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
			/*0060*/ 0x64, 0x67, (byte)0xC7, (byte)0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
			/*006D*/ 0x64, 0x67, (byte)0xC7, (byte)0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
			/*007A*/ 0x64, 0x67, (byte)0xC7, (byte)0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
			/*0087*/ 0x64, 0x67, (byte)0xC7, (byte)0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
			/*0094*/ (byte)0xB0, 0x10,// mov al,10h
		};
		int[] expectedInstructionOffsets = new int[] {
			0x0000,
			0x0007,
			0x0009,
			0x0010,
			0x0012,
			0x001F,
			0x002C,
			0x0039,
			0x0046,
			0x0053,
			0x0060,
			0x006D,
			0x007A,
			0x0087,
			0x0094,
		};
		RelocInfo[] expectedRelocInfos = new RelocInfo[0];
		final int options = BlockEncoderOptions.NONE;
		encodeBase(bitness, origRip, originalData, newRip, newData, options, DECODER_OPTIONS, expectedInstructionOffsets, expectedRelocInfos);
	}

	@Test
	void jkcc_near_bwd_short() {
		byte[] originalData = new byte[] {
			/*0000*/ (byte)0xB0, 0x10,// mov al,10h
			/*0002*/ (byte)0xC5, (byte)0xD0, (byte)0x84, (byte)0xF7, (byte)0xFF, (byte)0xFF, (byte)0xFF,// jkzd k5, near ptr 0
			/*0009*/ (byte)0xB0, 0x00,// mov al,0
			/*000B*/ (byte)0xC5, (byte)0xD0, (byte)0x85, (byte)0xEE, (byte)0xFF, (byte)0xFF, (byte)0xFF,// jknzd k5, near ptr 0
			/*0012*/ (byte)0xB0, 0x01,// mov al,1
		};
		byte[] newData = new byte[] {
			/*0000*/ (byte)0xB0, 0x10,// mov al,10h
			/*0002*/ (byte)0xC4, (byte)0xE0, 0x50, 0x74, (byte)0xF9,// jkzd k5, short 0
			/*0007*/ (byte)0xB0, 0x00,// mov al,0
			/*0009*/ (byte)0xC4, (byte)0xE0, 0x50, 0x75, (byte)0xF2,// jknzd k5, short 0
			/*000E*/ (byte)0xB0, 0x01,// mov al,1
		};
		int[] expectedInstructionOffsets = new int[] {
			0x0000,
			0x0002,
			0x0007,
			0x0009,
			0x000E,
		};
		RelocInfo[] expectedRelocInfos = new RelocInfo[0];
		final int options = BlockEncoderOptions.NONE;
		encodeBase(bitness, origRip, originalData, newRip, newData, options, DECODER_OPTIONS, expectedInstructionOffsets, expectedRelocInfos);
	}

	@Test
	void jkcc_near_bwd_near() {
		byte[] originalData = new byte[] {
			/*0000*/ 0x64, 0x67, (byte)0xC7, (byte)0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
			/*000D*/ 0x64, 0x67, (byte)0xC7, (byte)0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
			/*001A*/ 0x64, 0x67, (byte)0xC7, (byte)0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
			/*0027*/ 0x64, 0x67, (byte)0xC7, (byte)0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
			/*0034*/ 0x64, 0x67, (byte)0xC7, (byte)0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
			/*0041*/ 0x64, 0x67, (byte)0xC7, (byte)0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
			/*004E*/ 0x64, 0x67, (byte)0xC7, (byte)0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
			/*005B*/ 0x64, 0x67, (byte)0xC7, (byte)0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
			/*0068*/ 0x64, 0x67, (byte)0xC7, (byte)0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
			/*0075*/ 0x64, 0x67, (byte)0xC7, (byte)0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
			/*0082*/ 0x64, 0x67, (byte)0xC7, (byte)0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
			/*008F*/ 0x64, 0x67, (byte)0xC7, (byte)0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
			/*009C*/ (byte)0xC5, (byte)0xD0, (byte)0x84, 0x5D, (byte)0xFF, (byte)0xFF, (byte)0xFF,// jkzd k5, near ptr 0
			/*00A3*/ (byte)0xB0, 0x00,// mov al,0
			/*00A5*/ (byte)0xC5, (byte)0xD0, (byte)0x85, 0x54, (byte)0xFF, (byte)0xFF, (byte)0xFF,// jknzd k5, near ptr 0
			/*00AC*/ (byte)0xB0, 0x01,// mov al,1
		};
		byte[] newData = new byte[] {
			/*0000*/ 0x64, 0x67, (byte)0xC7, (byte)0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
			/*000D*/ 0x64, 0x67, (byte)0xC7, (byte)0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
			/*001A*/ 0x64, 0x67, (byte)0xC7, (byte)0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
			/*0027*/ 0x64, 0x67, (byte)0xC7, (byte)0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
			/*0034*/ 0x64, 0x67, (byte)0xC7, (byte)0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
			/*0041*/ 0x64, 0x67, (byte)0xC7, (byte)0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
			/*004E*/ 0x64, 0x67, (byte)0xC7, (byte)0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
			/*005B*/ 0x64, 0x67, (byte)0xC7, (byte)0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
			/*0068*/ 0x64, 0x67, (byte)0xC7, (byte)0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
			/*0075*/ 0x64, 0x67, (byte)0xC7, (byte)0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
			/*0082*/ 0x64, 0x67, (byte)0xC7, (byte)0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
			/*008F*/ 0x64, 0x67, (byte)0xC7, (byte)0x84, 0x0B, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,// mov dword ptr fs:[ebx+ecx+12345678h],12345678h
			/*009C*/ (byte)0xC5, (byte)0xD0, (byte)0x84, 0x5D, (byte)0xFF, (byte)0xFF, (byte)0xFF,// jkzd k5, near ptr 0
			/*00A3*/ (byte)0xB0, 0x00,// mov al,0
			/*00A5*/ (byte)0xC5, (byte)0xD0, (byte)0x85, 0x54, (byte)0xFF, (byte)0xFF, (byte)0xFF,// jknzd k5, near ptr 0
			/*00AC*/ (byte)0xB0, 0x01,// mov al,1
		};
		int[] expectedInstructionOffsets = new int[] {
			0x0000,
			0x000D,
			0x001A,
			0x0027,
			0x0034,
			0x0041,
			0x004E,
			0x005B,
			0x0068,
			0x0075,
			0x0082,
			0x008F,
			0x009C,
			0x00A3,
			0x00A5,
			0x00AC,
		};
		RelocInfo[] expectedRelocInfos = new RelocInfo[0];
		final int options = BlockEncoderOptions.NONE;
		encodeBase(bitness, origRip, originalData, newRip, newData, options, DECODER_OPTIONS, expectedInstructionOffsets, expectedRelocInfos);
	}

	@Test
	void jkcc_near_other_short() {
		byte[] originalData = new byte[] {
			/*0000*/ (byte)0xB0, 0x10,// mov al,10h
			/*0002*/ (byte)0xC5, (byte)0xD0, (byte)0x84, 0x0B, 0x00, 0x00, 0x00,// jkzd k5, near ptr 14h
			/*0009*/ (byte)0xB0, 0x00,// mov al,0
			/*000B*/ (byte)0xC5, (byte)0xD0, (byte)0x85, 0x02, 0x00, 0x00, 0x00,// jknzd k5, near ptr 14h
			/*0012*/ (byte)0xB0, 0x01,// mov al,1
		};
		byte[] newData = new byte[] {
			/*0000*/ (byte)0xB0, 0x10,// mov al,10h
			/*0002*/ (byte)0xC4, (byte)0xE0, 0x50, 0x74, 0x0E,// jkzd k5, short 0
			/*0007*/ (byte)0xB0, 0x00,// mov al,0
			/*0009*/ (byte)0xC4, (byte)0xE0, 0x50, 0x75, 0x07,// jknzd k5, short 0
			/*000E*/ (byte)0xB0, 0x01,// mov al,1
		};
		int[] expectedInstructionOffsets = new int[] {
			0x0000,
			0x0002,
			0x0007,
			0x0009,
			0x000E,
		};
		RelocInfo[] expectedRelocInfos = new RelocInfo[0];
		final int options = BlockEncoderOptions.NONE;
		encodeBase(bitness, origRip, originalData, origRip - 1, newData, options, DECODER_OPTIONS, expectedInstructionOffsets, expectedRelocInfos);
	}

	@Test
	void jkcc_near_other_near() {
		byte[] originalData = new byte[] {
			/*0000*/ (byte)0xB0, 0x10,// mov al,10h
			/*0002*/ (byte)0xC5, (byte)0xD0, (byte)0x84, 0x0B, 0x00, 0x00, 0x00,// jkzd k5, near ptr 14h
			/*0009*/ (byte)0xB0, 0x00,// mov al,0
			/*000B*/ (byte)0xC5, (byte)0xD0, (byte)0x85, 0x02, 0x00, 0x00, 0x00,// jknzd k5, near ptr 14h
			/*0012*/ (byte)0xB0, 0x01,// mov al,1
		};
		byte[] newData = new byte[] {
			/*0000*/ (byte)0xB0, 0x10,// mov al,10h
			/*0002*/ (byte)0xC5, (byte)0xD0, (byte)0x84, 0x0B, (byte)0xF0, (byte)0xFF, (byte)0xFF,// jkzd k5, near ptr 14h
			/*0009*/ (byte)0xB0, 0x00,// mov al,0
			/*000B*/ (byte)0xC5, (byte)0xD0, (byte)0x85, 0x02, (byte)0xF0, (byte)0xFF, (byte)0xFF,// jknzd k5, near ptr 14h
			/*0012*/ (byte)0xB0, 0x01,// mov al,1
		};
		int[] expectedInstructionOffsets = new int[] {
			0x0000,
			0x0002,
			0x0009,
			0x000B,
			0x0012,
		};
		RelocInfo[] expectedRelocInfos = new RelocInfo[0];
		final int options = BlockEncoderOptions.NONE;
		encodeBase(bitness, origRip, originalData, origRip + 0x1000, newData, options, DECODER_OPTIONS, expectedInstructionOffsets, expectedRelocInfos);
	}

	@Test
	void jkcc_near_other_long() {
		byte[] originalData = new byte[] {
			/*0000*/ (byte)0xC5, (byte)0xD0, (byte)0x84, 0x0C, 0x00, 0x00, 0x00,// jkzd k5, near ptr 13h
			/*0007*/ (byte)0xB0, 0x00,// mov al,0
			/*0009*/ (byte)0xC5, (byte)0xD0, (byte)0x85, 0x04, 0x00, 0x00, 0x00,// jknzd k5, near ptr 14h
			/*0010*/ (byte)0xB0, 0x01,// mov al,1
			/*0012*/ (byte)0x90,// nop
		};
		byte[] newData = new byte[] {
			/*0000*/ (byte)0xC4, (byte)0xE0, 0x50, 0x75, 0x06,// jknzd k5, short 0Bh
			/*0005*/ (byte)0xFF, 0x25, 0x15, 0x00, 0x00, 0x00,// jmp qword ptr [8000000000000020h]
			/*000B*/ (byte)0xB0, 0x00,// mov al,0
			/*000D*/ (byte)0xC4, (byte)0xE0, 0x50, 0x74, 0x06,// jkzd k5, short 18h
			/*0012*/ (byte)0xFF, 0x25, 0x10, 0x00, 0x00, 0x00,// jmp qword ptr [8000000000000028h]
			/*0018*/ (byte)0xB0, 0x01,// mov al,1
			/*001A*/ (byte)0x90,// nop
			/*001B*/ (byte)0xCC, (byte)0xCC, (byte)0xCC, (byte)0xCC, (byte)0xCC,
			/*0020*/ 0x13, (byte)0xDE, (byte)0xBC, (byte)0x9A, 0x78, 0x56, 0x34, 0x12,
			/*0028*/ 0x14, (byte)0xDE, (byte)0xBC, (byte)0x9A, 0x78, 0x56, 0x34, 0x12,
		};
		int[] expectedInstructionOffsets = new int[] {
			0xFFFF_FFFF,
			0x000B,
			0xFFFF_FFFF,
			0x0018,
			0x001A,
		};
		RelocInfo[] expectedRelocInfos = new RelocInfo[] {
			new RelocInfo(RelocKind.OFFSET64, 0x8000000000000020L),
			new RelocInfo(RelocKind.OFFSET64, 0x8000000000000028L),
		};
		final int options = BlockEncoderOptions.NONE;
		final long origRip = 0x123456789ABCDE00L;
		encodeBase(bitness, origRip, originalData, newRip, newData, options, DECODER_OPTIONS, expectedInstructionOffsets, expectedRelocInfos);
	}

	@Test
	void jkcc_near_fwd_short_no_opt() {
		byte[] originalData = new byte[] {
			/*0000*/ (byte)0xC5, (byte)0xD0, (byte)0x84, 0x0B, 0x00, 0x00, 0x00,// jkzd k5, near ptr 12h
			/*0007*/ (byte)0xB0, 0x00,// mov al,0
			/*0009*/ (byte)0xC5, (byte)0xD0, (byte)0x85, 0x02, 0x00, 0x00, 0x00,// jknzd k5, near ptr 12h
			/*0010*/ (byte)0xB0, 0x01,// mov al,1
			/*0012*/ (byte)0xB0, 0x10,// mov al,10h
		};
		byte[] newData = new byte[] {
			/*0000*/ (byte)0xC5, (byte)0xD0, (byte)0x84, 0x0B, 0x00, 0x00, 0x00,// jkzd k5, near ptr 12h
			/*0007*/ (byte)0xB0, 0x00,// mov al,0
			/*0009*/ (byte)0xC5, (byte)0xD0, (byte)0x85, 0x02, 0x00, 0x00, 0x00,// jknzd k5, near ptr 12h
			/*0010*/ (byte)0xB0, 0x01,// mov al,1
			/*0012*/ (byte)0xB0, 0x10,// mov al,10h
		};
		int[] expectedInstructionOffsets = new int[] {
			0x0000,
			0x0007,
			0x0009,
			0x0010,
			0x0012,
		};
		RelocInfo[] expectedRelocInfos = new RelocInfo[0];
		final int options = BlockEncoderOptions.DONT_FIX_BRANCHES;
		encodeBase(bitness, origRip, originalData, newRip, newData, options, DECODER_OPTIONS, expectedInstructionOffsets, expectedRelocInfos);
	}
}
